Service的启动流程

您所在的位置:网站首页 starservice failed Service的启动流程

Service的启动流程

2023-04-14 19:23| 来源: 网络整理| 查看: 265

最近在重温Android系统的相关知识点,我们都知道Android有四大组件,Activity、Service、Broadcast Receive、Content Provider,像对比其他知识点来说,重温四大组件最好的方式就是跟着源码再走一遍,说起看源码,我们可能会比较头疼,这是因为一旦扎进去,就会陷在代码的海洋里,不知所措,其实分析源码,最忌讳的是一上来就深挖。这样很难出来,不仅费时间,而且也提取不到有用的信息,最好的方式就是先按照主线流程走一遍,先把主线打通,有时间的话,再对支线进行旁敲侧击。

好,现在按照我们刚刚讲的方式来分析,今天我们主要分析service的启动流程,首先我们知道启动service有两种方式:startServicebindService,也就是service的启动和绑定,接下来我们先分析service的启动。

startService

首先我们从context.startService()这个方法为起点进行分析,我们看下他的源码:

@Override public ComponentName startService(Intent service) { return mBase.startService(service); }

startService()是一个抽象方法,具体实现在ContextImpl.java里,进入ContextImpl.java看下:

@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser); }

又会直接走到startServiceCommon这个方法里,

private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground, getOpPackageName(), getAttributionTag(), user.getIdentifier()); if (cn != null) { if (cn.getPackageName().equals("!")) { throw new SecurityException( "Not allowed to start service " + service + " without permission " + cn.getClassName()); } else if (cn.getPackageName().equals("!!")) { throw new SecurityException( "Unable to start service " + service + ": " + cn.getClassName()); } else if (cn.getPackageName().equals("?")) { throw new IllegalStateException( "Not allowed to start service " + service + ": " + cn.getClassName()); } } return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }

从startServiceCommon这个方法中,很容易定位到重点代码:

ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground, getOpPackageName(), getAttributionTag(), user.getIdentifier());

通过ActivityManager.getService()就会走到AMS中,在AMS里来启动service。

接下来进入AMS,一探究竟:

@Override public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, String callingFeatureId, int userId) throws TransactionTooLargeException { ... try { res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, callingFeatureId, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }

在这个方法里,会通过ActiveServices调用startServiceLocked,再看startServiceLocked:

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, final int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service + " type=" + resolvedType + " args=" + service.getExtras()); final boolean callerFg; if (caller != null) { // 这里记录app的进程信息 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); ... ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); ... return cmp; }

最终调用startServiceInnerLocked,继续看这个方法:

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ... String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); if (error != null) { return new ComponentName("!!", error); } ... return r.name; }

继续调用了bringUpServiceLocked,

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { ... // Service is now being launched, its package can't be stopped. try { AppGlobals.getPackageManager().setPackageStoppedState( r.packageName, false, r.userId); } catch (RemoteException e) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + r.packageName + ": " + e); } final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0; final String procName = r.processName; HostingRecord hostingRecord = new HostingRecord("service", r.instanceName); ProcessRecord app; if (!isolated) { app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app); //如果service进程存在 if (app != null && app.thread != null) { try { app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats); //启动service realStartServiceLocked(r, app, execInFg); return null; } catch (TransactionTooLargeException e) { throw e; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e); } } } else { app = r.isolatedProc; if (WebViewZygote.isMultiprocessEnabled() && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) { hostingRecord = HostingRecord.byWebviewZygote(r.instanceName); } if ((r.serviceInfo.flags & ServiceInfo.FLAG_USE_APP_ZYGOTE) != 0) { hostingRecord = HostingRecord.byAppZygote(r.instanceName, r.definingPackageName, r.definingUid); } } // 如果不存在此进程 if (app == null && !permissionsReviewRequired) { // 启动运行的线程 if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) { String msg = "Unable to launch app " + r.appInfo.packageName + "/" + r.appInfo.uid + " for service " + r.intent.getIntent() + ": process is bad"; Slog.w(TAG, msg); bringDownServiceLocked(r); return msg; } if (isolated) { r.isolatedProc = app; } } ... return null; }

这个方法做了两件事:

1.如果Service进程已经存在,则直接调用realStartServiceLocked。

2.如果Service进程不存在,则执行startProcessLocked方法创建进程,经过层层调用,最终也会走到

realStartServiceLocked中。

private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ... try { ... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState()); r.postNotification(); created = true; } }

这个方法内部调用了app.thread.scheduleCreateService,而app.thread是一个IApplicationThread类型的,他的实现是ActivityThread的一个内部类ApplicationThread,而这个类正好实现了IApplicationThread.Stub,在ApplicationThread类中,找到对应的调用方法:

public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false); CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s); }

可以看出,是发送一个消息给Handler,这个Handler是ActivityThread的内部类H

public void handleMessage(Message msg) { switch (msg.what) { ... case CREATE_SERVICE: if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj))); } handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; ... } }

最终调用了handleCreateService方法:

private void handleCreateService(CreateServiceData data) { LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { //创建service的context ContextImpl context = ContextImpl.createAppContext(this, packageInfo); //创建Application Application app = packageInfo.makeApplication(false, mInstrumentation); //获取类加载器 java.lang.ClassLoader cl = packageInfo.getClassLoader(); //加载service实例 service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); // Service resources must be initialized with the same loaders as the application // context. context.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0])); context.setOuterContext(service); //初始化service service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); //调用service的onCreate方法 service.onCreate(); mServices.put(data.token, service); try { //通过serviceDoneExecuting告知AMS,service已经启动完成 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } }

来看下这个方法做了哪些事情:

1.首先,创建上下文

2.创建Application,获取类加载器

3.加载service实例,初始化service, 回调通知开发者service创建完成。

4.最后通知AMS,service启动完成。

到这里service已经启动完成。

总结:

整个startService过程,从进程的角度看Service的启动流程

proccessA进程采用Binder形式向system_server进程发起startService请求system_server进程收到请求后,向zygote进程发送创建进程的请求zygote进程fork出新的进程,创建出新进程的ActivityThread的main方法新进程通过Binder向system_server进程发起attachApplication请求system_server进程收到请求后,经过一系列的在准备后,通过Binder向新进程发送scheduleCreateService请求新进程收到请求后,通过Handler发送CREATE_SERVICE消息主线程收到message,创建Service,并回调onCreate

在这里插入图片描述

bindService

接下来我们分析service的绑定:

无独有偶,也是先从context.bindService这个方法为起点进行分析,看源码:

@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { return mBase.bindService(service, conn, flags); }

同样也是返回bindService,在context的实现类ContextImpl.java中,

@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser()); }

调用了bindServiceCommon,来看下:

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName, Handler handler, Executor executor, UserHandle user) { ... try { ... int res = ActivityManager.getService().bindIsolatedService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, instanceName, getOpPackageName(), user.getIdentifier()); ... } }

通过ActivityManager.getService()来进入AMS,通过AMS调用bindIsolatedService方法,进入AMS里的这个方法看下:

public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String instanceName, String callingPackage, int userId) throws TransactionTooLargeException { ... synchronized(this) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, instanceName, callingPackage, userId); } }

会通过ActiveServices调用bindServiceLocked,继续分析:

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String instanceName, String callingPackage, final int userId) throws TransactionTooLargeException { ... //记录进程信息 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); ... //Activity信息 ActivityServiceConnectionsHolder activity = null; if (token != null) { activity = mAm.mAtmInternal.getServiceConnectionsHolder(token); if (activity == null) { Slog.w(TAG, "Binding with unknown activity: " + token); return 0; } } ... try { ... //如果设置了BIND_AUTO_CREATE标志,则启动bringUpServiceLocked方法, if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { return 0; } } ... if (s.app != null && b.intent.received) { // Service is already running, so we can immediately // publish the connection. try { c.conn.connected(s.name, b.intent.binder, false); } catch (Exception e) { Slog.w(TAG, "Failure sending service " + s.shortInstanceName + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } // If this is the first app connected back to this binding, // and the service had previously asked to be told when // rebound, then do so. if (b.intent.apps.size() == 1 && b.intent.doRebind) { requestServiceBindingLocked(s, b.intent, callerFg, true); } } else if (!b.intent.requested) { requestServiceBindingLocked(s, b.intent, callerFg, false); } maybeLogBindCrossProfileService(userId, callingPackage, callerApp.info.uid); getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s); } finally { Binder.restoreCallingIdentity(origId); } return 1; }

这个方法会先获取进程与Activity等信息,然后获取Service与应用程序的关系,【注意的是:如果存在了设置BIND_AUTO_CREATE的连接,就不销毁服务直接返回,启动bringUpServiceLocked方法,后面参考Service启动】后面调用requestServiceBindingLocked方法。

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { ... try { bumpServiceExecutingLocked(r, execInFg, "bind"); r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.getReportedProcState()); if (!rebind) { i.requested = true; } i.hasBound = true; i.doRebind = false; } return true; }

这里的app.thread和service启动那一块是一样的,是一个IApplicationThread类型的,,它的实现是ActivityThread的内部类ApplicationThread, 其中ApplicationThread继承了IApplicationThread.Stub

public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { updateProcessState(processState, false); BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; s.rebind = rebind; if (DEBUG_SERVICE) Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid=" + Binder.getCallingUid() + " pid=" + Binder.getCallingPid()); sendMessage(H.BIND_SERVICE, s); }

看到这个方法里,通过sendMessage把消息交给Handler,通过handleMessage来处理消息

public void handleMessage(Message msg) { switch (msg.what) { ... case BIND_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind"); handleBindService((BindServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; ... } }

最后还是调用了handleBindService,

final ArrayMap mServices = new ArrayMap(); private void handleBindService(BindServiceData data) { Service s = mServices.get(data.token); if (DEBUG_SERVICE) Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind); if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); try { if (!data.rebind) { IBinder binder = s.onBind(data.intent); ActivityManager.getService().publishService( data.token, data.intent, binder); } else { s.onRebind(data.intent); ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to bind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } }

mService是一个存着token与Server关系的Map,先从中获取要绑定的Service,再判断Service是否初次绑定, 是的话回调onBind方法并调用AMS的publishService方法;否则回调onRebind并调用AMS的serviceDoneExecuting方法。

我们先看下publishService方法:

public void publishService(IBinder token, Intent intent, IBinder service) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { if (!(token instanceof ServiceRecord)) { throw new IllegalArgumentException("Invalid service token"); } mServices.publishServiceLocked((ServiceRecord)token, intent, service); } }

通过ActiveServices调用publishServiceLocked:

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r + " " + intent + ": " + service); if (r != null) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); if (b != null && !b.received) { b.binder = service; b.requested = true; b.received = true; ArrayMap connections = r.getConnections(); for (int conni = connections.size() - 1; conni >= 0; conni--) { ArrayList clist = connections.valueAt(conni); for (int i=0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3